/*
Copyright (C) 2009-2010 Xanadu Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "../provider/DataProvider.h"
#include "PlayerQuests.h"
#include "../tools/PacketCreator.h"
#include "Player.h"
#include "Quest.h"
#include "../client/QuestsData.h"
#include "../client/QuestData.h"
#include "../client/QuestRewardsData.h"
#include "../client/QuestRewardData.h"
#include "../client/QuestRequestsData.h"
#include "../client/QuestRequestData.h"
#include "PlayerSkills.h"
#include "Skill.h"
#include "PlayerInventory.h"
#include "Item.h"
#include "../net/world/Worlds.h"

PlayerQuests::~PlayerQuests() {
	for (hash_map<int, Quest*>::iterator iter = pquests.begin(); iter != pquests.end(); iter++) {
		delete iter->second;
	}
	for (hash_map<int, Quest*>::iterator iter = cquests.begin(); iter != cquests.end(); iter++) {
		delete iter->second;
	}
}

void PlayerQuests::giveQuest(int questid, int npcid) {
	Quest* quest = new Quest(questid);
	pquests[questid] = quest;
	player->send(PacketCreator().startQuest(quest));
	rewardsData(questid, true);
	addQuestReqs(questid);
}

Quest* PlayerQuests::getQuestByID(int questid) {
	if (cquests.find(questid) != cquests.end())
		return cquests[questid];
	else if(pquests.find(questid) != pquests.end())
		return pquests[questid];
	return 0;
}

void PlayerQuests::completeQuest(int questid, int npcid, int selection, bool force) {
	cquests[questid] = pquests[questid];
	if(pquests[questid] == 0)
		return;
	pquests.erase(questid);
	Quest* quest = cquests[questid];
	quest->setIsCompleted(true);
	QuestData* questd = DataProvider::getInstance()->getQuestData(questid);
	player->send(PacketCreator().updateQuestInfo(quest));
	player->send(PacketCreator().updateQuest(quest, npcid, questd->getNextQuest()));
	rewardsData(questid, false);
}

void PlayerQuests::removeQuest(short questid) {
	pquests.erase(questid);
	player->send(PacketCreator().forfeitQuest(questid));
}

void PlayerQuests::initializePlayerQuests(int questid, bool isComplete, int mob, int amount) {
	if (isComplete == false) {
		Quest *quest = new Quest(questid);
		pquests[questid] = quest;
		addQuestReqs(questid);
		if (mob != 0 && amount != 0) {
			quest->addKilledMob(mob, amount);
		}
		player->send(PacketCreator().updateQuestInfo(quest));
	}
	else if (isComplete == true) {
		Quest *quest = new Quest(questid, true);
		cquests[questid] = quest;
		player->send(PacketCreator().updateQuestInfo(quest));
	}
}

void PlayerQuests::rewardsData(int questid, bool start) {
	QuestData* questd = DataProvider::getInstance()->getQuestData(questid);
	vector<QuestRewardData*> *rewards = questd->getRewardsData()->getData();
	for(int i = 0; i < (int)rewards->size(); i++) {
		if(rewards->at(i)->getStart() == start){
			if(rewards->at(i)->getGender() == 2 || rewards->at(i)->getGender() == player->getGender()) {
				if(rewards->at(i)->getJob() == -1 || rewards->at(i)->getJob() == player->getJob()) {
					if(rewards->at(i)->getItem()) {
						player->giveItem(rewards->at(i)->getID(), rewards->at(i)->getCount());
					}
					else if(rewards->at(i)->getExp()) {
						int exp = Worlds::getInstance()->getQuestExpRate() * rewards->at(i)->getID();
						player->setExp(player->getExp() + exp);
						player->send(PacketCreator().gainExp(exp, true, true));
					}
					else if(rewards->at(i)->getFame()) {
						player->setFame(player->getFame() + rewards->at(i)->getID());
						player->send(PacketCreator().fameGainChat(rewards->at(i)->getFame()));
					}
					else if(rewards->at(i)->getMesos()) {
						player->giveMesos(rewards->at(i)->getID());
					}
					else if(rewards->at(i)->getSkill()) {
						Skill* skill = player->getSkills()->getSkill(rewards->at(i)->getID());
						skill->setMasterLevel(rewards->at(i)->getMasterLevel());
						int newlevel = rewards->at(i)->getCount() + skill->getLevel();
						if(newlevel <= skill->getMasterLevel())
							skill->setLevel(newlevel);
						else
							skill->setLevel(rewards->at(i)->getCount());
					}
				}
			}
		}
	}
}

void PlayerQuests::addQuestReqs(int questid) {
	Quest* quest = pquests[questid];
	if (quest == 0)
		return;
	QuestData* questd = DataProvider::getInstance()->getQuestData(questid);
	vector<QuestRequestData*> *reqs= questd->getRequestsData()->getData();
	vector<int> mobs2;
	for (int i = 0; i < (int)reqs->size(); i++) {
		if (reqs->at(i)->getMob()) {
			mobs2.push_back(reqs->at(i)->getID());
		}
	}
	quest->addKilledMobsInfo(mobs2);
}

void PlayerQuests::giveAgain(int questid, int itemid) {
	Quest* quest = pquests[questid];
	bool droppedall = false;
	if (quest == 0)
		return;
	QuestData* questd = DataProvider::getInstance()->getQuestData(questid);
	Item* item = player->getInventories()->getItemByID(itemid);
	if (item == 0)
		droppedall = true;
	vector<QuestRewardData*> *rewards = questd->getRewardsData()->getData();
	int ramount;
	for (int i = 0; i < (int)rewards->size(); i++) {
		if (rewards->at(i)->getStart()) {
			if (rewards->at(i)->getID() == itemid) {
				ramount = rewards->at(i)->getCount();
				break;
			}
		}
	}
	if(droppedall) {
		player->giveItem(itemid, ramount);
	} else {
		item->setAmount(ramount);
		player->send(PacketCreator().updateSlot(item));
	}
}